package com.sdy.dcsb.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.StringUtil;
import com.sdy.dcsb.biz.model.EsbDictionary;
import com.sdy.dcsb.biz.model.EsbInboundParam;
import com.sdy.dcsb.biz.model.EsbInboundParamDic;
import com.sdy.dcsb.biz.service.EsbDictionaryService;
import com.sdy.dcsb.biz.service.EsbInboundParamDicService;
import com.sdy.dcsb.biz.service.EsbInboundParamService;
import com.sdy.dcsb.biz.util.ConditionUtil;
import com.sdy.dcsb.web.util.ChineseUtil;
import com.sdy.dcsb.web.util.SearchBrowserKeywordsUtil;
import com.sdy.mvc.controller.BaseController;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author Snaky
 * @date 2020/5/8
 */
@Slf4j
@Controller
@RequestMapping("/EsbDictionary")
@Api(tags = "接口封装字典值配置相关接口")
public class EsbDictionaryController extends BaseController {
    @Autowired
    private EsbDictionaryService dictionaryService;
    @Autowired
    private EsbInboundParamService paramService;
    @Autowired
    private EsbInboundParamDicService paramDicService;

    /** excel文件后缀 */
    private static final String SUFFIX_EXCEL_FILE = ".xls";

    @GetMapping("/pageData")
    @ApiOperation(value = "查询已存在字典配置信息")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "name", value = "字典名称，可为空，模糊查询"),
            @ApiImplicitParam(dataType = "Integer", name = "current", value = "当前页，默认为1"),
            @ApiImplicitParam(dataType = "Integer", name = "size", value = "分页大小，默认为10")
    })
    @ResponseBody
    public Response pageData(String name, Integer current, Integer size) throws Exception{
        if(size == null || size <= 0){
            size = 10;
        }
        if(current == null || current <= 0){
            current = 1;
        }
        name = ChineseUtil.decode(name);
        return Response.success(dictionaryService.getPageData(new Page<>(current, size, 0),name));
    }

    @GetMapping("/getDetail")
    @ApiOperation(value = "查询字典配置详情")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "dicName", value = "字典名称，必传")
    })
    @ResponseBody
    public Response getDetail(String dicName, Integer current, Integer size) throws Exception{
        Assert.isBlank(dicName,"字典名称为空");
        if(size == null || size <= 0){
            size = 10;
        }
        if(current == null || current <= 0){
            current = 1;
        }

        dicName = ChineseUtil.decode(dicName);
        return Response.success(dictionaryService.getDetail(new Page<>(current, size,0),dicName));
    }


    @GetMapping("/save")
    @ApiOperation(value = "单条字典值保存/修改")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Integer", name = "dicName", value = "字典名称"),
            @ApiImplicitParam(dataType = "String", name = "dicKey", value = "字典值key"),
            @ApiImplicitParam(dataType = "String", name = "dicValue", value = "字典值value")
    })
    @ResponseBody
    public Response save(String dicName, String dicKey, String dicValue) throws Exception{
        Assert.isBlank(dicName,"字典名称为空");
        Assert.isBlank(dicKey,"字典值key为空");
        Assert.isBlank(dicValue,"字典值value为空");

        dicName = ChineseUtil.decode(dicName);
        dicKey = ChineseUtil.decode(dicKey);
        dicValue = ChineseUtil.decode(dicValue);

        QueryWrapper<EsbDictionary> wrapper = new QueryWrapper<>();
        wrapper.eq("dic_name",dicName)
                .eq("dic_key",dicKey);
        EsbDictionary esbDictionary = dictionaryService.getOne(wrapper);
        boolean flag;
        if(esbDictionary == null){
            // 新增
            esbDictionary = new EsbDictionary();
            esbDictionary.setDicName(dicName)
                    .setDicKey(dicKey)
                    .setDicValue(dicValue)
                    .setCreateDate(new Date());
            flag = dictionaryService.save(esbDictionary);
        } else {
            // 更新
            esbDictionary.setDicValue(dicValue)
                    .setCreateDate(new Date());
            flag = dictionaryService.update(esbDictionary,wrapper);
        }

        return flag ? Response.success("保存成功"):Response.error("保存失败");
    }

    @GetMapping("/delete")
    @ApiOperation(value = "删除所有字典配置")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "dicName", value = "字典名称，必传")
    })
    @ResponseBody
    public Response delete(String dicName) throws Exception{
        Assert.isBlank(dicName,"字典名称为空");
        dicName = ChineseUtil.decode(dicName);

        QueryWrapper<EsbDictionary> wrapper = new QueryWrapper<>();
        wrapper.eq("dic_name",dicName);
        boolean flag = dictionaryService.remove(wrapper);
        return flag ? Response.success() : Response.error("删除失败");
    }

    @GetMapping("/deleteSingle")
    @ApiOperation(value = "单条字典值删除")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Integer", name = "id", value = "字典配置id，必传")
    })
    @ResponseBody
    public Response deleteSingle(Integer id) throws Exception{
        Assert.notTrue(ConditionUtil.isValidId(id),"字典配置id为空");

        boolean flag = dictionaryService.removeById(id);
        return flag ? Response.success() : Response.error("删除失败");
    }

    @GetMapping("/templateExport")
    @ApiOperation("字典配置模板excel导出")
    @ApiImplicitParams({
    })
    public Response templateExport(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            Resource res = new ClassPathResource("/webapp/public/template/layout/字典配置模板.xls");
            InputStream ins = res.getInputStream();
            OutputStream ops = response.getOutputStream();
            byte[] buffer = new byte[10240];
            response.setContentType("text/html;charset=utf-8");
            boolean isIe = SearchBrowserKeywordsUtil.isMSBrowser(request);
            String fileName = res.getFilename();
            if(isIe){
                fileName = URLEncoder.encode(fileName , "UTF-8");
            } else {
                fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            }
            response.setHeader("Content-Disposition", "attachment; filename="+ fileName+".xls");
            int bytesRead;
            while((bytesRead = ins.read(buffer, 0, buffer.length)) != -1){
                ops.write(buffer, 0, bytesRead);
            }
            ops.close();
            ins.close();
        } catch (IOException e) {
            e.printStackTrace();
            return Response.error("字典配置模板导出失败:"+e.getMessage());
        }
        return Response.success();
    }

    @PostMapping("/uploadExcel")
    @ApiOperation(value = "excel上传，批量保存字典值")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "dicName", value = "字典名称，必传")
    })
    @ResponseBody
    public Response upload(@RequestPart("file") MultipartFile file, @RequestParam("dicName")String dicName) throws Exception{
        Assert.isBlank(dicName,"字典名称为空");
        if(file == null){
            return Response.error("文件为空");
        }
        InputStream inputStream = null;
        boolean flag;
        try {
            dicName = ChineseUtil.decode(dicName);
            String filename = file.getOriginalFilename();
            if(!filename.endsWith(SUFFIX_EXCEL_FILE)){
                return Response.error("文件类型错误");
            }
            inputStream = file.getInputStream();
            HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
            HSSFSheet sheetAt = workbook.getSheetAt(0);
            List<EsbDictionary> dictionaryList = new ArrayList<>();
            Date now = new Date();
            for (Row row : sheetAt) {
                //首行（即表头）不读取
                if (row.getRowNum() == 0) {
                    continue;
                }
                //读取当前行中单元格数据，索引从0开始
                Cell cell1 = row.getCell(0);
                Cell cell2 = row.getCell(1);
                cell1.setCellType(CellType.STRING);
                cell2.setCellType(CellType.STRING);
                String dicKey = cell1.getStringCellValue();
                String dicValue = cell2.getStringCellValue();
                EsbDictionary dictionary = new EsbDictionary();
                dictionary.setDicName(dicName)
                        .setDicKey(dicKey)
                        .setDicValue(dicValue)
                        .setCreateDate(now);
                dictionaryList.add(dictionary);
            }
            if(dictionaryList.size() ==  0){
                return Response.error("文件内容为空");
            }
            // 清空之前配置信息
            QueryWrapper<EsbDictionary> wrapper = new QueryWrapper<>();
            wrapper.eq("dic_name",dicName);
            dictionaryService.remove(wrapper);
            flag = dictionaryService.batchSave(dictionaryList);
        } catch (Exception e) {
            e.printStackTrace();
            return Response.error(e.getMessage());
        } finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag ? Response.success() : Response.error("导入失败");
    }

    @GetMapping("/fileExport")
    @ApiOperation("字典配置信息导出")
    @ApiImplicitParams({
            @ApiImplicitParam(name="dicName", value="字典名称", required=true)
    })
    public Response fileExport(String dicName,HttpServletRequest request, HttpServletResponse response) throws Exception {
        Assert.isBlank(dicName,"字典名称为空");

        try {
            dicName = ChineseUtil.decode(dicName);
            QueryWrapper<EsbDictionary> wrapper = new QueryWrapper<>();
            wrapper.eq("dic_name",dicName);
            List<EsbDictionary> list = dictionaryService.list(wrapper);
            if(list == null || list.size() == 0){
                return Response.error("暂无字典配置信息");
            }

            HSSFWorkbook wb = new HSSFWorkbook();
            HSSFSheet sheet = wb.createSheet("字典配置信息");
            HSSFRow titleRow = sheet.createRow(0);
            // /设置行的高度
            titleRow.setHeightInPoints(20);
            // 表格样式
            HSSFCellStyle titleStyle = wb.createCellStyle();
            HSSFFont font = wb.createFont();
            font.setFontHeightInPoints((short) 12);
            font.setBold(true);
            titleStyle.setFont(font);

            HSSFCell cell1 = titleRow.createCell(0);
            cell1.setCellValue("字典名称");
            cell1.setCellStyle(titleStyle);
            HSSFCell cell2 = titleRow.createCell(1);
            cell2.setCellValue("字典关键字");
            cell2.setCellStyle(titleStyle);
            HSSFCell cell3 = titleRow.createCell(2);
            cell3.setCellValue("字典转换值");
            cell3.setCellStyle(titleStyle);
            for (EsbDictionary dictionary : list) {
                HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum()+1);
                dataRow.createCell(0).setCellValue(dicName);
                dataRow.createCell(1).setCellValue(dictionary.getDicKey());
                dataRow.createCell(2).setCellValue(dictionary.getDicValue());
                dataRow.setHeightInPoints(15);
            }
            // 根据实际效果，拟合所得公式 width = 256 * 列宽 + 184
            sheet.setColumnWidth(0,  256 * 25 + 184);
            sheet.setColumnWidth(1,  256 * 25 + 184);
            sheet.setColumnWidth(2,  256 * 25 + 184);

            boolean isIe = SearchBrowserKeywordsUtil.isMSBrowser(request);
            String fileName = dicName + "字典配置信息";
            if(isIe){
                fileName = URLEncoder.encode(fileName , "UTF-8");
            } else {
                fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            }
            response.setHeader("Content-Disposition", "attachment; filename="+ fileName+".xls");
            OutputStream outputStream = response.getOutputStream();
            wb.write(outputStream);
            outputStream.flush();
            outputStream.close();
            wb.close();
        } catch (Exception e) {
            e.printStackTrace();
            Response.error("字典配置信息导出错误：" + e.getMessage());
        }
        return Response.success();
    }

    @GetMapping("/saveParamDic")
    @ApiOperation(value = "保存/更新 参数字典关联信息")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "dicName", value = "字典名称，为空表示删除已关联信息"),
            @ApiImplicitParam(dataType = "Integer", name = "paramId", value = "参数id，必传")
    })
    @ResponseBody
    public Response saveParamDic(Integer paramId, String dicName) throws Exception{
        Assert.notTrue(ConditionUtil.isValidId(paramId),"参数id为空");

        EsbInboundParam inboundParam = paramService.getById(paramId);
        if(inboundParam == null){
            return Response.error("参数id不存在");
        }

        QueryWrapper<EsbInboundParamDic> paramDicWrapper = new QueryWrapper<>();
        paramDicWrapper.eq("param_id",paramId);
        if(StringUtil.isBlank(dicName)){
            // 删除关联
            boolean flag = paramDicService.remove(paramDicWrapper);
            return flag ? Response.success("删除成功"):Response.error("删除失败");
        }

        dicName = ChineseUtil.decode(dicName);
        QueryWrapper<EsbDictionary> dictionaryWrapper = new QueryWrapper<>();
        dictionaryWrapper.eq("dic_name",dicName);
        List<EsbDictionary> dictionaryList = dictionaryService.list(dictionaryWrapper);
        if(dictionaryList == null || dictionaryList.size() == 0){
            return Response.error("字典名称不存在");
        }
        if(inboundParam.getParamMode() != 2){
            return Response.error("只有出参可配置字典");
        }
        EsbInboundParamDic paramDic = paramDicService.getOne(paramDicWrapper);
        boolean flag;
        if(paramDic == null){
            // 新增
            paramDic = new EsbInboundParamDic();
            paramDic.setParamId(paramId).setDicName(dicName).setCreateDate(new Date());
            flag = paramDicService.save(paramDic);
        } else {
            // 更新
            paramDic.setDicName(dicName);
            flag = paramDicService.update(paramDic,paramDicWrapper);
        }
        return flag ? Response.success("保存成功"):Response.error("保存失败");
    }

}
